<template>
  <div class="avatar-crop-container">
    <!-- 选择图片按钮 -->
    <div class="select-image-container">
      <div class="avatar-placeholder" @click="triggerFileSelect">
        <span v-if="!initialAvatar" class="avatar-icon">👤</span>
        <img v-else :src="initialAvatar" class="avatar-preview" alt="当前头像">
        <span class="upload-text">点击选择头像</span>
      </div>
      <input 
        ref="fileInput" 
        type="file" 
        accept="image/*" 
        style="display: none"
        @change="handleFileSelect"
      >
    </div>

    <!-- 对话框形式的裁剪界面 -->
    <div v-if="showDialog" class="dialog-overlay" @click.self="cancel">
      <div class="dialog-content">
        <div class="crop-header">
          <button class="action-button cancel-button" @click="cancel">取消</button>
          <h3 class="crop-title">裁剪头像</h3>
          <button class="action-button confirm-button" @click="confirmCrop">确认上传</button>
        </div>
        
        <div class="crop-canvas-wrapper">
          <!-- 裁剪提示 -->
          <div class="crop-instructions">
            <span>请拖动图片调整位置</span>
          </div>
          
          <!-- 图片容器 -->
          <div class="image-container">
            <img 
              ref="cropImage"
              :src="imageUrl" 
              class="crop-image"
              :style="{
                left: dragPosition.x + 'px',
                top: dragPosition.y + 'px',
                transform: `scale(${scale})`,
                transition: isDragging ? 'none' : 'transform 0.2s ease'
              }"
              @mousedown="startDrag"
              @touchstart="startDrag"
              @mousewheel="handleWheel"
              @wheel="handleWheel"
            >
            
            <!-- 裁剪框 -->
            <div class="crop-box">
              <!-- 裁剪框边框 -->
              <div class="crop-box-border"></div>
              <!-- 裁剪框遮罩 -->
              <div class="crop-box-overlay"></div>
            </div>
          </div>
        </div>
        
        <!-- 缩放控制 -->
        <div class="scale-controls">
          <button class="scale-button" @click="zoomOut" :disabled="scale <= minScale">缩小</button>
          <span class="scale-value">{{ Math.round(scale * 100) }}%</span>
          <button class="scale-button" @click="zoomIn">放大</button>
        </div>
      </div>
    </div>
  </div>
</template>

<script>
export default {
  name: 'AvatarCrop',
  props: {
    // 可选的初始头像URL
    initialAvatar: {
      type: String,
      default: ''
    }
  },
  data() {
    return {
      imageUrl: '',
      originalImageUrl: '',
      showDialog: false,
      isDragging: false,
      dragPosition: { x: 0, y: 0 },
      startDragPosition: { x: 0, y: 0 },
      scale: 1,
      minScale: 0.1, // 允许缩小图片，最小为原图的10%
      cropSize: 100
    }
  },
  watch: {
    initialAvatar(newVal) {
      if (newVal && !this.imageUrl) {
        this.imageUrl = newVal
        this.originalImageUrl = newVal
      }
    }
  },
  mounted() {
    // 如果提供了初始头像，设置为当前图片
    if (this.initialAvatar) {
      this.imageUrl = this.initialAvatar
      this.originalImageUrl = this.initialAvatar
    }
    
    // 添加全局鼠标/触摸事件监听
    document.addEventListener('mousemove', this.onDrag)
    document.addEventListener('mouseup', this.stopDrag)
    document.addEventListener('touchmove', this.onDrag)
    document.addEventListener('touchend', this.stopDrag)
  },
  beforeDestroy() {
    // 清理事件监听
    document.removeEventListener('mousemove', this.onDrag)
    document.removeEventListener('mouseup', this.stopDrag)
    document.removeEventListener('touchmove', this.onDrag)
    document.removeEventListener('touchend', this.stopDrag)
  },
  methods: {
    // 触发文件选择
    triggerFileSelect() {
      this.$refs.fileInput.click()
    },
    
    // 处理文件选择
    handleFileSelect(e) {
      const file = e.target.files[0]
      if (file) {
        // 验证文件类型
        if (!file.type.match('image.*')) {
          this.$message.error('请选择图片文件！')
          return
        }
        
        // 不再限制图片大小，允许上传任意大小的图片
        
        
        // 读取图片并显示
        const reader = new FileReader()
        reader.onload = (e) => {
          this.imageUrl = e.target.result
          this.originalImageUrl = e.target.result
          this.resetPosition()
          this.showDialog = true // 显示对话框
          // this.$message.info('请拖动图片调整裁剪区域')
        }
        reader.readAsDataURL(file)
      }
      
      // 清空input，以便可以重复选择相同的文件
      this.$refs.fileInput.value = ''
    },
    
    // 重置位置和缩放
    resetPosition() {
      this.scale = 1
      
      // 尝试将图片居中显示在选取框中
      this.$nextTick(() => {
        const cropImage = this.$refs.cropImage
        if (cropImage && this.imageUrl) {
          const imageContainer = cropImage.parentElement
          const containerRect = imageContainer.getBoundingClientRect()
          
          // 获取图片原始尺寸
          const imageNaturalWidth = cropImage.naturalWidth || cropImage.width
          const imageNaturalHeight = cropImage.naturalHeight || cropImage.height
          
          // 计算容器中心点
          const centerX = containerRect.width / 2
          const centerY = containerRect.height / 2
          
          // 计算缩放后的图片尺寸
          const scaledWidth = imageNaturalWidth * this.scale
          const scaledHeight = imageNaturalHeight * this.scale
          
          // 裁剪框尺寸
          const cropBoxWidth = 100
          const cropBoxHeight = 100
          
          // 优先确保图片在可视区域内完全显示
          const imageContainerWidth = containerRect.width
          const imageContainerHeight = containerRect.height
          
          // 计算图片边界的安全范围
          let safeX, safeY
          
          // 如果图片宽度小于容器宽度，居中显示
          if (scaledWidth < imageContainerWidth) {
            safeX = (imageContainerWidth - scaledWidth) / 2
          } else {
            // 否则限制在安全边界内
            const minX = -scaledWidth + imageContainerWidth
            const maxX = 0
            safeX = Math.max(minX, Math.min(centerX - (imageNaturalWidth / 2) * this.scale, maxX))
          }
          
          // 如果图片高度小于容器高度，居中显示
          if (scaledHeight < imageContainerHeight) {
            safeY = (imageContainerHeight - scaledHeight) / 2
          } else {
            // 否则限制在安全边界内
            const minY = -scaledHeight + imageContainerHeight
            const maxY = 0
            safeY = Math.max(minY, Math.min(centerY - (imageNaturalHeight / 2) * this.scale, maxY))
          }
          
          // 设置初始位置
          this.dragPosition.x = safeX
          this.dragPosition.y = safeY
          
          // 然后确保裁剪框的四个边界始终在原始图片范围内
          // 计算裁剪框的边界坐标（相对于容器）
          const cropBoxLeft = centerX - cropBoxWidth / 2
          const cropBoxTop = centerY - cropBoxHeight / 2
          const cropBoxRight = centerX + cropBoxWidth / 2
          const cropBoxBottom = centerY + cropBoxHeight / 2
          
          // 计算图片的边界坐标（相对于容器）
          const imageLeft = this.dragPosition.x
          const imageTop = this.dragPosition.y
          const imageRight = imageLeft + scaledWidth
          const imageBottom = imageTop + scaledHeight
          
          // 检查并调整位置，确保裁剪框完全在原图范围内
          // 左边界检查
          if (cropBoxLeft < imageLeft) {
            this.dragPosition.x -= (imageLeft - cropBoxLeft)
          }
          // 右边界检查
          if (cropBoxRight > imageRight) {
            this.dragPosition.x += (cropBoxRight - imageRight)
          }
          // 上边界检查
          if (cropBoxTop < imageTop) {
            this.dragPosition.y -= (imageTop - cropBoxTop)
          }
          // 下边界检查
          if (cropBoxBottom > imageBottom) {
            this.dragPosition.y += (cropBoxBottom - imageBottom)
          }
        } else {
          // 如果图片还未加载，设置为默认位置
          this.dragPosition = { x: 0, y: 0 }
        }
      })
    },
    
    // 开始拖动
    startDrag(e) {
      e.preventDefault()
      this.isDragging = true
      
      const clientX = e.type.includes('mouse') ? e.clientX : e.touches[0].clientX
      const clientY = e.type.includes('mouse') ? e.clientY : e.touches[0].clientY
      
      this.startDragPosition = {
        x: clientX - this.dragPosition.x,
        y: clientY - this.dragPosition.y
      }
    },
    
    // 拖动中
    onDrag(e) {
      if (!this.isDragging) return
      
      const clientX = e.type.includes('mouse') ? e.clientX : e.touches[0].clientX
      const clientY = e.type.includes('mouse') ? e.clientY : e.touches[0].clientY
      
      // 计算新的拖动位置
      const newDragX = clientX - this.startDragPosition.x
      const newDragY = clientY - this.startDragPosition.y
      
      // 获取图片和容器信息进行边界检查
      const cropImage = this.$refs.cropImage
      if (cropImage) {
        const imageContainer = cropImage.parentElement
        const containerRect = imageContainer.getBoundingClientRect()
        
        // 获取图片原始尺寸
        const imageNaturalWidth = cropImage.naturalWidth || cropImage.width
        const imageNaturalHeight = cropImage.naturalHeight || cropImage.height
        
        // 计算缩放后的图片尺寸
        const scaledWidth = imageNaturalWidth * this.scale
        const scaledHeight = imageNaturalHeight * this.scale
        
        // 裁剪框尺寸和位置
        const cropBoxWidth = 100
        const cropBoxHeight = 100
        const centerX = containerRect.width / 2
        const centerY = containerRect.height / 2
        
        // 优先确保图片在可视区域内完全显示
        const imageContainerWidth = containerRect.width
        const imageContainerHeight = containerRect.height
        
        // 计算图片边界的安全范围
        let safeX = newDragX
        let safeY = newDragY
        
        // 如果图片宽度小于容器宽度，居中显示
        if (scaledWidth < imageContainerWidth) {
          safeX = (imageContainerWidth - scaledWidth) / 2
        } else {
          // 否则限制在安全边界内
          const minX = -scaledWidth + imageContainerWidth
          const maxX = 0
          safeX = Math.max(minX, Math.min(newDragX, maxX))
        }
        
        // 如果图片高度小于容器高度，居中显示
        if (scaledHeight < imageContainerHeight) {
          safeY = (imageContainerHeight - scaledHeight) / 2
        } else {
          // 否则限制在安全边界内
          const minY = -scaledHeight + imageContainerHeight
          const maxY = 0
          safeY = Math.max(minY, Math.min(newDragY, maxY))
        }
        
        // 首先设置临时位置为安全范围
        let adjustedX = safeX
        let adjustedY = safeY
        
        // 然后确保裁剪框的四个边界始终在原始图片范围内
        // 计算裁剪框的边界坐标（相对于容器）
        const cropBoxLeft = centerX - cropBoxWidth / 2
        const cropBoxTop = centerY - cropBoxHeight / 2
        const cropBoxRight = centerX + cropBoxWidth / 2
        const cropBoxBottom = centerY + cropBoxHeight / 2
        
        // 计算新位置下图片的边界坐标（相对于容器）
        const imageLeft = adjustedX
        const imageTop = adjustedY
        const imageRight = imageLeft + scaledWidth
        const imageBottom = imageTop + scaledHeight
        
        // 检查并调整位置，确保裁剪框完全在原图范围内
        // 左边界检查：裁剪框左边界不能小于图片左边界
        if (cropBoxLeft < imageLeft) {
          adjustedX -= (imageLeft - cropBoxLeft)
        }
        // 右边界检查：裁剪框右边界不能大于图片右边界
        if (cropBoxRight > imageRight) {
          adjustedX += (cropBoxRight - imageRight)
        }
        // 上边界检查：裁剪框上边界不能小于图片上边界
        if (cropBoxTop < imageTop) {
          adjustedY -= (imageTop - cropBoxTop)
        }
        // 下边界检查：裁剪框下边界不能大于图片下边界
        if (cropBoxBottom > imageBottom) {
          adjustedY += (cropBoxBottom - imageBottom)
        }
        
        // 最终设置拖动位置
        this.dragPosition = {
          x: adjustedX,
          y: adjustedY
        }
      } else {
        // 如果图片元素不存在，直接设置位置
        this.dragPosition = {
          x: newDragX,
          y: newDragY
        }
      }
    },
    
    // 停止拖动
    stopDrag() {
      this.isDragging = false
    },
    
    // 处理鼠标滚轮缩放
    handleWheel(e) {
      e.preventDefault()
      
      const delta = e.deltaY > 0 ? -0.1 : 0.1
      this.zoomAtCenter(delta)
    },
    
    // 放大
    zoomIn() {
      this.zoomAtCenter(0.1)
    },
    
    // 缩小
    zoomOut() {
      if (this.scale > this.minScale) {
        this.zoomAtCenter(-0.1)
      }
    },
    
    // 在选取框中心进行缩放
    zoomAtCenter(delta) {
      const cropImage = this.$refs.cropImage
      if (!cropImage) return
      
      const oldScale = this.scale
      const newScale = Math.max(this.minScale, this.scale + delta)
      this.scale = newScale
      
      // 计算选取框中心相对于图片容器的位置
      const imageContainer = cropImage.parentElement
      const containerRect = imageContainer.getBoundingClientRect()
      const centerX = containerRect.width / 2
      const centerY = containerRect.height / 2
      
      // 获取图片原始尺寸
      const imageNaturalWidth = cropImage.naturalWidth || cropImage.width
      const imageNaturalHeight = cropImage.naturalHeight || cropImage.height
      
      // 计算缩放后的图片尺寸
      const scaledWidth = imageNaturalWidth * newScale
      const scaledHeight = imageNaturalHeight * newScale
      
      // 计算裁剪框的尺寸和位置
      const cropBoxWidth = 100 // 从样式中获取的裁剪框宽度
      const cropBoxHeight = 100 // 从样式中获取的裁剪框高度
      
      // 计算需要调整的偏移量，使图片在缩放后保持在选取框中心
      this.dragPosition.x = centerX - (imageNaturalWidth / 2) * newScale
      this.dragPosition.y = centerY - (imageNaturalHeight / 2) * newScale
      
      // 优先确保图片在可视区域内完全显示
      // 当图片缩小时，确保用户能看到完整的原图
      const imageContainerWidth = containerRect.width
      const imageContainerHeight = containerRect.height
      
      // 计算图片边界的安全范围
      let safeX = this.dragPosition.x
      let safeY = this.dragPosition.y
      
      // 如果图片宽度小于容器宽度，居中显示
      if (scaledWidth < imageContainerWidth) {
        safeX = (imageContainerWidth - scaledWidth) / 2
      } else {
        // 否则限制在安全边界内
        const minX = -scaledWidth + imageContainerWidth
        const maxX = 0
        safeX = Math.max(minX, Math.min(this.dragPosition.x, maxX))
      }
      
      // 如果图片高度小于容器高度，居中显示
      if (scaledHeight < imageContainerHeight) {
        safeY = (imageContainerHeight - scaledHeight) / 2
      } else {
        // 否则限制在安全边界内
        const minY = -scaledHeight + imageContainerHeight
        const maxY = 0
        safeY = Math.max(minY, Math.min(this.dragPosition.y, maxY))
      }
      
      // 调整位置以确保图片完整显示
      this.dragPosition.x = safeX
      this.dragPosition.y = safeY
      
      // 然后确保裁剪框的四个边界始终在原始图片范围内
      // 计算裁剪框的边界坐标（相对于容器）
      const cropBoxLeft = centerX - cropBoxWidth / 2
      const cropBoxTop = centerY - cropBoxHeight / 2
      const cropBoxRight = centerX + cropBoxWidth / 2
      const cropBoxBottom = centerY + cropBoxHeight / 2
      
      // 计算图片的边界坐标（相对于容器）
      const imageLeft = this.dragPosition.x
      const imageTop = this.dragPosition.y
      const imageRight = imageLeft + scaledWidth
      const imageBottom = imageTop + scaledHeight
      
      // 检查并调整位置，确保裁剪框完全在原图范围内
      // 左边界检查
      if (cropBoxLeft < imageLeft) {
        this.dragPosition.x -= (imageLeft - cropBoxLeft)
      }
      // 右边界检查
      if (cropBoxRight > imageRight) {
        this.dragPosition.x += (cropBoxRight - imageRight)
      }
      // 上边界检查
      if (cropBoxTop < imageTop) {
        this.dragPosition.y -= (imageTop - cropBoxTop)
      }
      // 下边界检查
      if (cropBoxBottom > imageBottom) {
        this.dragPosition.y += (cropBoxBottom - imageBottom)
      }
    },
    
    // 确认裁剪
    confirmCrop() {
      // 创建canvas进行裁剪
      const canvas = document.createElement('canvas')
      const ctx = canvas.getContext('2d')
      canvas.width = this.cropSize
      canvas.height = this.cropSize
      
      const cropImage = this.$refs.cropImage
      const img = new Image()
      img.src = this.imageUrl
      
      img.onload = () => {
        // 计算裁剪位置
        const cropBoxSize = this.cropSize
        const imageContainer = cropImage.parentElement
        const containerRect = imageContainer.getBoundingClientRect()
        const imageRect = cropImage.getBoundingClientRect()
        
        // 计算相对位置和缩放比例
        const scaleX = img.width / imageRect.width * this.scale
        const scaleY = img.height / imageRect.height * this.scale
        
        // 计算选取框中心点在容器中的位置
        const cropBoxCenterX = containerRect.width / 2
        const cropBoxCenterY = containerRect.height / 2
        
        // 计算图片左上角相对于容器的偏移量
        const imageOffsetX = this.dragPosition.x
        const imageOffsetY = this.dragPosition.y
        
        // 计算裁剪区域的左上角坐标（相对于原图）
        const cropX = (cropBoxCenterX - imageOffsetX - cropBoxSize / 2) * scaleX
        const cropY = (cropBoxCenterY - imageOffsetY - cropBoxSize / 2) * scaleY
        
        // 确保裁剪区域在有效范围内
        const safeCropX = Math.max(0, Math.min(cropX, img.width - cropBoxSize * scaleX))
        const safeCropY = Math.max(0, Math.min(cropY, img.height - cropBoxSize * scaleY))
        
        // 在canvas上绘制裁剪后的图像（只绘制选取框内的部分）
        ctx.drawImage(
          img,
          safeCropX,          // 源图像开始裁剪的x坐标
          safeCropY,          // 源图像开始裁剪的y坐标
          cropBoxSize * scaleX, // 源图像裁剪的宽度
          cropBoxSize * scaleY, // 源图像裁剪的高度
          0,                  // 目标canvas的x坐标
          0,                  // 目标canvas的y坐标
          cropBoxSize,        // 目标canvas的宽度
          cropBoxSize         // 目标canvas的高度
        )
        
        // 将canvas转换为Blob对象，设置质量参数为0.8进行压缩
        canvas.toBlob((blob) => {
          const croppedFile = new File([blob], 'avatar_cropped.png', { type: 'image/png' })
          
          // 触发上传事件，提供预览URL和文件对象
          this.$emit('avatar-selected', {
            previewUrl: canvas.toDataURL(),
            file: croppedFile
          })
          
          // 关闭对话框
          this.showDialog = false
          this.imageUrl = ''
        }, 'image/png', 0.8) // 添加质量参数，压缩图片
      }
    },
    
    // 取消
    cancel() {
      this.showDialog = false
      this.imageUrl = ''
      this.resetPosition()
    }
  }
}
</script>

<style scoped>
.avatar-crop-container {
  display: flex;
  flex-direction: column;
  align-items: center;
  padding: 16px;
}

/* 对话框遮罩层 */
.dialog-overlay {
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
  background-color: rgba(0, 0, 0, 0.5);
  display: flex;
  justify-content: center;
  align-items: center;
  z-index: 1000;
}

/* 对话框内容 */
.dialog-content {
  width: 90%;
  max-width: 500px;
  max-height: 90vh;
  overflow-y: auto;
  border-radius: 8px;
  background-color: #fff;
  box-shadow: 0 4px 20px rgba(0, 0, 0, 0.15);
  animation: dialogFadeIn 0.3s ease;
}

/* 对话框动画 */
@keyframes dialogFadeIn {
  from {
    opacity: 0;
    transform: scale(0.9);
  }
  to {
    opacity: 1;
    transform: scale(1);
  }
}

/* 当前头像预览 */
.avatar-preview {
  width: 60px;
  height: 60px;
  border-radius: 50%;
  object-fit: cover;
  margin-bottom: 8px;
}

/* 选择图片界面 */
.select-image-container {
  width: 100%;
  display: flex;
  justify-content: center;
}

.avatar-placeholder {
  width: 100px;
  height: 100px;
  border-radius: 50%;
  background-color: #f0f0f0;
  display: flex;
  flex-direction: column;
  justify-content: center;
  align-items: center;
  cursor: pointer;
  border: 2px dashed #ccc;
  transition: all 0.3s ease;
  position: relative;
}

.avatar-placeholder:hover {
  background-color: #e0e0e0;
  border-color: #409eff;
}

.avatar-icon {
  font-size: 32px;
  margin-bottom: 8px;
}

.upload-text {
  font-size: 12px;
  color: #666;
  text-align: center;
}

.size-hint {
  font-size: 10px;
  color: #999;
  position: absolute;
  bottom: -20px;
  left: 50%;
  transform: translateX(-50%);
}

/* 裁剪界面 */
.crop-container {
  width: 100%;
  max-width: 400px;
  border-radius: 8px;
  background-color: #fff;
  overflow: hidden;
  box-shadow: 0 2px 12px rgba(0, 0, 0, 0.1);
}

.crop-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding: 12px 16px;
  border-bottom: 1px solid #f0f0f0;
}

.crop-title {
  margin: 0;
  font-size: 16px;
  font-weight: 500;
  color: #333;
}

.action-button {
  padding: 6px 16px;
  border: none;
  border-radius: 4px;
  font-size: 14px;
  cursor: pointer;
  transition: background-color 0.3s ease;
}

.cancel-button {
  background-color: #f5f5f5;
  color: #666;
}

.cancel-button:hover {
  background-color: #e0e0e0;
}

.confirm-button {
  background-color: #409eff;
  color: #fff;
}

.confirm-button:hover {
  background-color: #66b1ff;
}

.crop-canvas-wrapper {
  position: relative;
  width: 100%;
  height: 300px;
  overflow: hidden;
  background-color: #f8f8f8;
  display: flex;
  flex-direction: column;
  align-items: center;
}

.crop-instructions {
  margin-top: 16px;
  font-size: 14px;
  color: #666;
}

.image-container {
  position: relative;
  width: 200px;
  height: 200px;
  margin-top: 16px;
  overflow: hidden;
  background-color: #fff;
}

.crop-image {
  position: absolute;
  max-width: none;
  cursor: move;
  user-select: none;
}

/* 裁剪框样式 */
.crop-box {
  position: absolute;
  top: 50px;
  left: 50px;
  width: 100px;
  height: 100px;
  overflow: hidden;
}

.crop-box-border {
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
  border: 2px dashed #409eff;
  box-sizing: border-box;
  pointer-events: none;
}

.crop-box-overlay {
  position: absolute;
  top: -50px;
  left: -50px;
  right: -50px;
  bottom: -50px;
  background-color: rgba(0, 0, 0, 0.5);
  box-shadow: inset 0 0 0 50px rgba(255, 255, 255, 0.5);
  pointer-events: none;
}

/* 缩放控制 */
.scale-controls {
  display: flex;
  justify-content: center;
  align-items: center;
  padding: 16px;
  gap: 16px;
  background-color: #fafafa;
  border-top: 1px solid #f0f0f0;
}

.scale-button {
  padding: 6px 12px;
  border: 1px solid #dcdfe6;
  background-color: #fff;
  color: #606266;
  border-radius: 4px;
  cursor: pointer;
  font-size: 14px;
  transition: all 0.3s ease;
}

.scale-button:hover:not(:disabled) {
  border-color: #409eff;
  color: #409eff;
}

.scale-button:disabled {
  cursor: not-allowed;
  opacity: 0.5;
}

/* 优化移动端体验 */
@media (max-width: 768px) {
  .dialog-content {
    width: 95%;
    margin: 20px;
  }
}

.scale-value {
  font-size: 14px;
  color: #606266;
  min-width: 50px;
  text-align: center;
}

/* 移动端适配 */
@media (max-width: 768px) {
  .crop-container {
    width: 95%;
  }
  
  .crop-canvas-wrapper {
    height: 250px;
  }
  
  .image-container {
    width: 180px;
    height: 180px;
  }
  
  .crop-box {
    top: 40px;
    left: 40px;
  }
}
</style>